<template>
  <main class="page" :style="pageStyle">
    <!-- 搜索 -->
    <section ref="pageSearchRef" class="page-search" v-show="showSearch">
      <div ref="form-ref" class="page-search-form">
        <div ref="form-container-ref">
          <!-- 搜索表单 -->
          <slot name="form"></slot>
        </div>
      </div>
      <!-- 搜索的操作按钮 -->
      <el-form inline :size="size" v-if="!hasScrollX" class="page-search-option">
        <el-form-item>
          <el-button type="primary" icon="el-icon-search" @click="getList">
            {{ $t('搜索') }}
          </el-button>
          <el-button icon="el-icon-refresh" @click="resetQuery">
            {{ $t('重置') }}
          </el-button>
        </el-form-item>
      </el-form>
    </section>
    <!-- 操作按钮&工具栏 -->
    <section class="page-actions" ref="pageActionsRef">
      <!-- 搜索的操作按钮 -->
      <el-form inline :size="size" v-if="hasScrollX && showSearch">
        <el-form-item>
          <el-button type="primary" icon="el-icon-search" @click="getList">
            {{ $t('搜索') }}
          </el-button>
          <el-button icon="el-icon-refresh" @click="resetQuery">
            {{ $t('重置') }}
          </el-button>
        </el-form-item>
      </el-form>
      <section class="page-actions-wrapper">
        <div class="actions-btns">
          <!-- 操作按钮 -->
          <slot name="actions" class="action-slot" />
        </div>

        <div class="actions-pagination-toobar">
          <div class="_pagination" v-if="!isMobile()">
            <!-- 头部分页 -->
            <slot name="pagination" v-if="!showEmpty"></slot>
          </div>
          <!-- 右侧工具栏 -->
          <el-row>
            <el-tooltip
              class="item"
              effect="dark"
              :content="showSearch ? $t('隐藏搜索') : $t('显示搜索')"
              placement="top"
              v-if="search"
            >
              <el-button size="mini" circle icon="el-icon-search" @click="toggleSearch()" />
            </el-tooltip>
            <el-tooltip class="item" effect="dark" content="刷新" placement="top">
              <el-button size="mini" circle icon="el-icon-refresh" @click="handleGetList" />
            </el-tooltip>
            <el-tooltip class="item" effect="dark" content="显隐列" placement="top" v-if="columns && !isMobile()">
              <el-button size="mini" circle icon="el-icon-menu" @click="showColumn()" />
            </el-tooltip>
          </el-row>
        </div>
      </section>
    </section>
    <!-- 表格 el-table  -->
    <section class="page-table">
      <el-empty v-if="showEmpty" :style="{ height: tableHeight + 'px' }" description="暂无数据" />
      <el-table v-else v-loading="loading" :height="tableHeight" ref="tableRef" :data="tableData" row-key="id">
        <template v-for="item in columns">
          <el-table-column align="center" :key="item.key" v-bind="columnOptions(item)" v-if="item.visible">
            <template #default="scope">
              <!-- 动态插槽 -->
              <template v-if="item.useSlot">
                <slot :name="item.prop" :row="scope.row"></slot>
              </template>
              <!-- 使用自定义render渲染 -->
              <template v-else-if="item.component">
                <component :is="item.component" :row="scope.row" :prop="item.prop" />
              </template>
              <template v-else>
                <!-- 是否有自定义 formatter -->
                <template v-if="item.formatter">
                  {{ item.formatter(scope.row[item.prop]) }}
                </template>
                <!-- 直接渲染文本 -->
                <template v-else>
                  {{ scope.row[item.prop] }}
                </template>
              </template>
            </template>
          </el-table-column>
        </template>
      </el-table>
    </section>
    <!-- 分页 -->
    <section>
      <slot name="pagination" v-if="!showEmpty"></slot>
    </section>

    <!-- transfer -->
    <el-dialog :title="$t('显示/隐藏')" width="800px" :visible.sync="transferVisible" append-to-body>
      <el-transfer class="custom-transfer" :titles="['显示', '隐藏']" v-model="transferValue" :data="columns" />
      <template #footer>
        <el-button type="primary" @click="handleTransfer">确认</el-button>
        <el-button @click="transferVisible = false">关闭</el-button>
      </template>
    </el-dialog>
  </main>
</template>

<script>
import { debounce } from '@/utils'

export default {
  name: 'ProTable',
  components: {},
  props: {
    /**
     * @type {import('vue').PropOptions<ProTableColumns>}
     * @return
     */
    columns: {
      type: Array,
    },
    tableData: {
      type: Array,
      required: true,
    },
    loading: {
      type: Boolean,
      default: () => false,
    },
    showSearch: {
      type: Boolean,
      required: true,
    },
    getList: {
      type: Function,
      required: true,
    },
    resetQuery: {
      type: Function,
      required: true,
    },
    /**
     * 搜索表单每一项的 width
     */
    searchFormItemWidth: {
      type: Number,
      default: () => 240,
    },
    size: {
      type: String,
      default: () => 'mini',
    },
  },

  data() {
    return {
      keyName: 'column-' + this.$route.name,
      tableHeight: 500,
      search: true,
      showEmpty: false,
      // 显隐数据
      transferValue: [],
      // 是否显示弹出层
      transferVisible: false,
      /**是否有横向滚动条 */
      hasScrollX: false,
    }
  },
  computed: {
    /**
     * @returns {string}
     */
    pageStyle() {
      return {
        '--item-width': `${this.searchFormItemWidth}px`,
      }
    },
    /**
     * @returns {string}
     */
    style() {
      return {
        marginRight: `5px`,
      }
    },
  },
  mounted() {
    window.addEventListener(
      'resize',
      debounce(() => {
        if (this.showSearch) {
          this.addEventListener()
        }
      }, 100),
    )
    this.columns?.forEach((i) => {
      i.key = `${this.keyName}-${i.prop}`
      i.visible = true
      if (i.label == this.$t('操作')) {
        i.disabled = true
      }
    })
    this.setTransferDefaultValue()
    this.handleTableHeight()
    this.handleShowEmpty()
  },
  watch: {
    showSearch: function (newValue) {
      this.handleTableHeight()
      if (newValue) {
        this.addEventListener()
      }
    },
  },
  methods: {
    handleShowOverflowTooltip(item) {
      let flag = true
      const names = [this.$t('操作'), this.$t('图片'), this.$t('主图')]
      if (names.includes(this.$t(item.label))) {
        flag = false
      }

      return flag
    },
    handleColumnDefaultWidth(item) {
      const columnDefaultWidth = 110
      let width = 0

      const names = [this.$t('操作')] //操作不设置宽度,不能隐藏，防止页面渲染问题
      if (!names.includes(this.$t(item.label))) {
        // width = item.width ? item.width : columnDefaultWidth
        width = item.width
      } else {
        width = null
      }
      return width
    },
    /**
     * 可直接添加 el-table-column 的属性值
     * @param item
     */
    columnOptions(item) {
      const options = {
        ...item,
        // 翻译一下,如果传入的值是中文, 方便后续
        label: this.$t(item.label),
        showOverflowTooltip: this.handleShowOverflowTooltip(item),
        width: this.handleColumnDefaultWidth(item),
      }
      return options
    },
    handleGetList() {
      this.getList()
      this.layout()
    },
    handleTransfer() {
      const _columns = JSON.parse(JSON.stringify(this.columns))
      _columns.forEach((i) => (i.visible = true))
      this.transferValue.map((i) => {
        const index = _columns.findIndex((item) => item.key == i)
        if (index > -1) {
          _columns[index].visible = false
        }
      })
      localStorage.setItem(this.keyName, JSON.stringify(this.transferValue))
      this.$emit('update:columns', _columns)
      this.transferVisible = false
      this.handleShowEmpty()
      this.layout()
    },
    layout() {
      setTimeout(() => {
        this.$nextTick(() => this.$refs['tableRef']?.doLayout())
      }, 100)
    },
    handleShowEmpty() {
      this.$nextTick(() => {
        if (this.columns && this.columns.filter((i) => i.visible).length == 0) {
          this.showEmpty = true
        } else {
          this.showEmpty = false
        }
      })
    },
    /**计算表格高度 */
    handleTableHeight() {
      this.$nextTick(() => {
        const headerHeight = 80
        const windowHeight = window.innerHeight
        const pageActionsHeight = this.$refs['pageActionsRef'].offsetHeight * 2
        const offsetHeight = 90

        // 是否显示搜索
        if (this.showSearch) {
          const pageSearchHeight = this.$refs['pageSearchRef'].offsetHeight
          this.tableHeight = windowHeight - pageSearchHeight - pageActionsHeight - headerHeight - offsetHeight
        } else {
          this.tableHeight = windowHeight - pageActionsHeight - headerHeight - offsetHeight
        }
      })
    },
    /**设置transfer的默认数据 */
    setTransferDefaultValue() {
      const values = JSON.parse(localStorage.getItem(this.keyName) || '[]')
      this.columns.forEach((column) => {
        if (values.includes(column.key)) {
          column.visible = false
        }
      })
      this.transferValue = values
    },
    // 搜索
    toggleSearch() {
      this.$emit('update:showSearch', !this.showSearch)
    },
    // 刷新
    refresh() {
      this.$emit('queryTable')
    },
    // 打开显隐列dialog
    showColumn() {
      this.transferVisible = true
    },

    addEventListener() {
      this.$nextTick(() => {
        try {
          // 选择需要监听的元素
          const el = this.$refs['form-ref']
          // 获取元素的初始宽度+右侧按钮宽度
          const seachWidth = this.$refs['form-container-ref'].clientWidth + 156
          if (el.scrollWidth > el.clientWidth || seachWidth > el.clientWidth) {
            this.hasScrollX = true
          } else {
            this.hasScrollX = false
          }
          // console.log(this.hasScrollX)
        } catch (error) {
          console.log(` error==>`, error)
        }
      })
    },
  },
}
</script>
<style lang="scss">
.page {
  display: flex;
  flex-direction: column;
  &-search {
    display: flex;
    position: relative;
    justify-content: space-between;
    position: relative;
    &-form {
      flex: 1;
      overflow: auto;
      display: flex;
      form {
        .el-row {
          display: flex;
          & > div {
            margin-right: 10px;
          }
          .el-form-item {
            .el-form-item__content {
              .vue-treeselect,
              .el-date-editor,
              .el-select,
              .el-input {
                width: var(--item-width);
              }
            }
          }
        }
      }
    }
    &-option {
      position: absolute;
      right: 0;
      top: 0;
    }
  }
  &-actions {
    margin-bottom: 10px;
    &-wrapper {
      text-align: right;
      display: flex;
      width: 100%;
      justify-content: space-between;
    }
    .actions-btns {
      display: flex;
      align-items: center;
      .action-slot {
        height: 25px;
        margin: 0;
        padding: 0;
      }
    }
    .actions-pagination-toobar {
      display: flex;
      ._pagination {
        & > .pagination-container {
          padding: 0 !important;
          height: 100% !important;
          margin: 0 40px 0 0 !important;
        }
      }
    }
  }

  //.page-table {
  //}
}
.custom-transfer {
  display: flex;
  align-items: center;
  justify-content: space-around;
  .el-transfer-panel {
    height: 500px;
    .el-transfer-panel__body {
      height: calc(100% - 40px);
      .el-transfer-panel__list {
        height: 100%;
      }
    }
  }
}
</style>
